/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Controllers;

import Controllers.exceptions.NonexistentEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import Entities.Pet;
import Entities.Vacine;
import java.util.ArrayList;
import java.util.List;
import Entities.Appointment;
import Entities.Record;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author Heinz Hernandez
 */
public class RecordJpaController implements Serializable {

    public RecordJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Record record) {
        if (record.getVacineList() == null) {
            record.setVacineList(new ArrayList<Vacine>());
        }
        if (record.getAppointmentList() == null) {
            record.setAppointmentList(new ArrayList<Appointment>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Pet petId = record.getPetId();
            if (petId != null) {
                petId = em.getReference(petId.getClass(), petId.getPetId());
                record.setPetId(petId);
            }
            List<Vacine> attachedVacineList = new ArrayList<Vacine>();
            for (Vacine vacineListVacineToAttach : record.getVacineList()) {
                vacineListVacineToAttach = em.getReference(vacineListVacineToAttach.getClass(), vacineListVacineToAttach.getVacId());
                attachedVacineList.add(vacineListVacineToAttach);
            }
            record.setVacineList(attachedVacineList);
            List<Appointment> attachedAppointmentList = new ArrayList<Appointment>();
            for (Appointment appointmentListAppointmentToAttach : record.getAppointmentList()) {
                appointmentListAppointmentToAttach = em.getReference(appointmentListAppointmentToAttach.getClass(), appointmentListAppointmentToAttach.getAppoId());
                attachedAppointmentList.add(appointmentListAppointmentToAttach);
            }
            record.setAppointmentList(attachedAppointmentList);
            em.persist(record);
            if (petId != null) {
                petId.getRecordList().add(record);
                petId = em.merge(petId);
            }
            for (Vacine vacineListVacine : record.getVacineList()) {
                Record oldRecIdOfVacineListVacine = vacineListVacine.getRecId();
                vacineListVacine.setRecId(record);
                vacineListVacine = em.merge(vacineListVacine);
                if (oldRecIdOfVacineListVacine != null) {
                    oldRecIdOfVacineListVacine.getVacineList().remove(vacineListVacine);
                    oldRecIdOfVacineListVacine = em.merge(oldRecIdOfVacineListVacine);
                }
            }
            for (Appointment appointmentListAppointment : record.getAppointmentList()) {
                Record oldRecIdOfAppointmentListAppointment = appointmentListAppointment.getRecId();
                appointmentListAppointment.setRecId(record);
                appointmentListAppointment = em.merge(appointmentListAppointment);
                if (oldRecIdOfAppointmentListAppointment != null) {
                    oldRecIdOfAppointmentListAppointment.getAppointmentList().remove(appointmentListAppointment);
                    oldRecIdOfAppointmentListAppointment = em.merge(oldRecIdOfAppointmentListAppointment);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Record record) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Record persistentRecord = em.find(Record.class, record.getRecId());
            Pet petIdOld = persistentRecord.getPetId();
            Pet petIdNew = record.getPetId();
            List<Vacine> vacineListOld = persistentRecord.getVacineList();
            List<Vacine> vacineListNew = record.getVacineList();
            List<Appointment> appointmentListOld = persistentRecord.getAppointmentList();
            List<Appointment> appointmentListNew = record.getAppointmentList();
            if (petIdNew != null) {
                petIdNew = em.getReference(petIdNew.getClass(), petIdNew.getPetId());
                record.setPetId(petIdNew);
            }
            List<Vacine> attachedVacineListNew = new ArrayList<Vacine>();
            for (Vacine vacineListNewVacineToAttach : vacineListNew) {
                vacineListNewVacineToAttach = em.getReference(vacineListNewVacineToAttach.getClass(), vacineListNewVacineToAttach.getVacId());
                attachedVacineListNew.add(vacineListNewVacineToAttach);
            }
            vacineListNew = attachedVacineListNew;
            record.setVacineList(vacineListNew);
            List<Appointment> attachedAppointmentListNew = new ArrayList<Appointment>();
            for (Appointment appointmentListNewAppointmentToAttach : appointmentListNew) {
                appointmentListNewAppointmentToAttach = em.getReference(appointmentListNewAppointmentToAttach.getClass(), appointmentListNewAppointmentToAttach.getAppoId());
                attachedAppointmentListNew.add(appointmentListNewAppointmentToAttach);
            }
            appointmentListNew = attachedAppointmentListNew;
            record.setAppointmentList(appointmentListNew);
            record = em.merge(record);
            if (petIdOld != null && !petIdOld.equals(petIdNew)) {
                petIdOld.getRecordList().remove(record);
                petIdOld = em.merge(petIdOld);
            }
            if (petIdNew != null && !petIdNew.equals(petIdOld)) {
                petIdNew.getRecordList().add(record);
                petIdNew = em.merge(petIdNew);
            }
            for (Vacine vacineListOldVacine : vacineListOld) {
                if (!vacineListNew.contains(vacineListOldVacine)) {
                    vacineListOldVacine.setRecId(null);
                    vacineListOldVacine = em.merge(vacineListOldVacine);
                }
            }
            for (Vacine vacineListNewVacine : vacineListNew) {
                if (!vacineListOld.contains(vacineListNewVacine)) {
                    Record oldRecIdOfVacineListNewVacine = vacineListNewVacine.getRecId();
                    vacineListNewVacine.setRecId(record);
                    vacineListNewVacine = em.merge(vacineListNewVacine);
                    if (oldRecIdOfVacineListNewVacine != null && !oldRecIdOfVacineListNewVacine.equals(record)) {
                        oldRecIdOfVacineListNewVacine.getVacineList().remove(vacineListNewVacine);
                        oldRecIdOfVacineListNewVacine = em.merge(oldRecIdOfVacineListNewVacine);
                    }
                }
            }
            for (Appointment appointmentListOldAppointment : appointmentListOld) {
                if (!appointmentListNew.contains(appointmentListOldAppointment)) {
                    appointmentListOldAppointment.setRecId(null);
                    appointmentListOldAppointment = em.merge(appointmentListOldAppointment);
                }
            }
            for (Appointment appointmentListNewAppointment : appointmentListNew) {
                if (!appointmentListOld.contains(appointmentListNewAppointment)) {
                    Record oldRecIdOfAppointmentListNewAppointment = appointmentListNewAppointment.getRecId();
                    appointmentListNewAppointment.setRecId(record);
                    appointmentListNewAppointment = em.merge(appointmentListNewAppointment);
                    if (oldRecIdOfAppointmentListNewAppointment != null && !oldRecIdOfAppointmentListNewAppointment.equals(record)) {
                        oldRecIdOfAppointmentListNewAppointment.getAppointmentList().remove(appointmentListNewAppointment);
                        oldRecIdOfAppointmentListNewAppointment = em.merge(oldRecIdOfAppointmentListNewAppointment);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = record.getRecId();
                if (findRecord(id) == null) {
                    throw new NonexistentEntityException("The record with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Record record;
            try {
                record = em.getReference(Record.class, id);
                record.getRecId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The record with id " + id + " no longer exists.", enfe);
            }
            Pet petId = record.getPetId();
            if (petId != null) {
                petId.getRecordList().remove(record);
                petId = em.merge(petId);
            }
            List<Vacine> vacineList = record.getVacineList();
            for (Vacine vacineListVacine : vacineList) {
                vacineListVacine.setRecId(null);
                vacineListVacine = em.merge(vacineListVacine);
            }
            List<Appointment> appointmentList = record.getAppointmentList();
            for (Appointment appointmentListAppointment : appointmentList) {
                appointmentListAppointment.setRecId(null);
                appointmentListAppointment = em.merge(appointmentListAppointment);
            }
            em.remove(record);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Record> findRecordEntities() {
        return findRecordEntities(true, -1, -1);
    }

    public List<Record> findRecordEntities(int maxResults, int firstResult) {
        return findRecordEntities(false, maxResults, firstResult);
    }

    private List<Record> findRecordEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Record.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Record findRecord(Long id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Record.class, id);
        } finally {
            em.close();
        }
    }

    public int getRecordCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Record> rt = cq.from(Record.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
